#include "MeasureTab.h"

#ifndef ROOT_TGButton
#include <TGButton.h>
#endif

#ifndef ROOT_TRootEmbeddedCanvas
#include <TRootEmbeddedCanvas.h>
#endif

#ifndef ROOT_TGraph
#include <TGraph.h>
#endif

#include <TGFileDialog.h>

#include <string>
#include <time.h>
#include <sstream>

#include <cmath>

MeasureTab::MeasureTab(void)
{
}

MeasureTab::~MeasureTab(void)
{
    //TODO: destroy everything here
}

void MeasureTab::Create( TGTab * fMainTabs, void* appPtr, std::string arcName )
{
     // container of "Graph Tab"
	TGCompositeFrame *fGraphTabFrame;
	fGraphTabFrame = fMainTabs->AddTab("Measurement Tab (main tab)");
	fGraphTabFrame->SetLayoutManager(new TGVerticalLayout(fGraphTabFrame));
	fGraphTabFrame->SetLayoutBroken(kTRUE);

	TGLabel *archiveNameLablel = new TGLabel(fGraphTabFrame,"Archive name");
	fGraphTabFrame->AddFrame(archiveNameLablel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	archiveNameLablel->MoveResize(16,40,76,16);

	// ???? ????? ???? ?? ?????? / Archieve name input field
	m_archiveName = new TGTextEntry(fGraphTabFrame, new TGTextBuffer(15));
	m_archiveName->SetMaxLength(255);
	m_archiveName->SetText(arcName.c_str());
	fGraphTabFrame->AddFrame(m_archiveName, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_archiveName->MoveResize(100,40,460,22);

        TGTextButton *browse = new TGTextButton(fGraphTabFrame,"Browse...");
        fGraphTabFrame->AddFrame(browse, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
        browse->MoveResize(570,40,70,22);
        browse->Connect("Pressed()", "AppGUI", appPtr, "BrowseArc()");

        TGTextButton *readCalibs = new TGTextButton(fGraphTabFrame,"Read calibrations");
        fGraphTabFrame->AddFrame(readCalibs, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
        readCalibs->MoveResize(570,70,128,22);
        readCalibs->Connect("Pressed()", "AppGUI", appPtr, "InvokeReadCalibrations()");

        TGTextButton *showArcInfo = new TGTextButton(fGraphTabFrame,"Show archive info");
        fGraphTabFrame->AddFrame(showArcInfo, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
        showArcInfo->MoveResize(570,100,128,22);
        showArcInfo->Connect("Pressed()", "AppGUI", appPtr, "ShowArcInfo()");

	TGLabel *shotNumLabel = new TGLabel(fGraphTabFrame,"Shot number");
	fGraphTabFrame->AddFrame(shotNumLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	shotNumLabel->MoveResize(680,40,82,16);

	// ???? ????? ?????? ???????? / Shot number input field 
	m_shotNumber = new TGTextEntry(fGraphTabFrame, new TGTextBuffer(15));
	fGraphTabFrame->AddFrame(m_shotNumber, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_shotNumber->MoveResize(760,40,88,22);

	TGTextButton *calculateButton = new TGTextButton(fGraphTabFrame,"Calculate");
	fGraphTabFrame->AddFrame(calculateButton, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	calculateButton->MoveResize(860,40,61,22);
	calculateButton->Connect("Pressed()",  "AppGUI", appPtr, "RunCalculate()");

	// embedded canvas
	TRootEmbeddedCanvas *fGraph = new TRootEmbeddedCanvas(0,fGraphTabFrame,544,448);
	Int_t wfGraph = fGraph->GetCanvasWindowId();
	m_canvas = new TCanvas("TomsonViewCanvas", 10, 10, wfGraph);
	fGraph->AdoptCanvas(m_canvas);
	fGraphTabFrame->AddFrame(fGraph, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	fGraph->MoveResize(16,80,544,448);

        m_grChanelWidth = new TGraph(2);
        m_grChanelWidth->SetLineColor(2);
	m_gr = new TGraph(2);

	m_pointsChanelWidth = new TGraphErrors(5);
        m_pointsChanelWidth->SetMarkerStyle(21);
        m_pointsChanelWidth->SetMarkerColor(4);
        m_pointsChanelWidth->SetTitle("Temperature");
        m_pointsChanelWidth->Draw("AP");

	m_points = new TGraphErrors(5);
        m_points->SetMarkerStyle(25);
        m_points->SetMarkerColor(1);
	
        m_canvas->Update();
        m_canvas->SetEditable(false);

	m_temperatureVal = new TGLabel(fGraphTabFrame,"");
	fGraphTabFrame->AddFrame(m_temperatureVal, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_temperatureVal->MoveResize(600,150,192,16);
        m_temperatureVal->SetTextJustify(kTextLeft);

        m_densityVal = new TGLabel(fGraphTabFrame,"");
	fGraphTabFrame->AddFrame(m_densityVal, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_densityVal->MoveResize(600,170,192,16);
        m_densityVal->SetTextJustify(kTextLeft);

        m_correction = new TGLabel(fGraphTabFrame,"");
	fGraphTabFrame->AddFrame(m_correction, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_correction->MoveResize(600,210,192,16);
        m_correction->SetTextJustify(kTextLeft);

        m_temperatureValNoCorrection = new TGLabel(fGraphTabFrame,"");
	fGraphTabFrame->AddFrame(m_temperatureValNoCorrection, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_temperatureValNoCorrection->MoveResize(600,230,192,16);
        m_temperatureValNoCorrection->SetTextJustify(kTextLeft);

        m_densityValNoCorrection = new TGLabel(fGraphTabFrame,"");
	fGraphTabFrame->AddFrame(m_densityValNoCorrection, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_densityValNoCorrection->MoveResize(600,250,192,16);
        m_densityValNoCorrection->SetTextJustify(kTextLeft);

	m_warning = new TGTextView(fGraphTabFrame);
	fGraphTabFrame->AddFrame(m_warning, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	m_warning->MoveResize(576,332,450,150);

        TGTextButton *clearWarning = new TGTextButton(fGraphTabFrame,"Clear");
	fGraphTabFrame->AddFrame(clearWarning, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	clearWarning->MoveResize(576,486,100,22);
	clearWarning->Connect("Pressed()", "MeasureTab", this, "ClearWarning()");
        
	TGLabel *fGraphTabWarningLabel = new TGLabel(fGraphTabFrame,"warning");
	fGraphTabWarningLabel->SetTextJustify(36);
	fGraphTabFrame->AddFrame(fGraphTabWarningLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
	fGraphTabWarningLabel->MoveResize(576,312,64,18);
}

std::string MeasureTab::GetArcName()
{
    TString name = m_archiveName->GetDisplayText();
    return std::string(name.Data());
}

int MeasureTab::GetShotNum()
{
    int shot = -1;
    if( m_shotNumber->GetDisplayText().IsDigit() )
        shot = m_shotNumber->GetDisplayText().Atoi();
    
    return shot;
}

void MeasureTab::ClearData()
{
    m_temperatureVal->SetText("");
    m_temperatureValNoCorrection->SetText("");

    DrawData(std::vector<std::pair<double, double> >(), std::vector<std::pair<double, ValueWithError> >());

}

void MeasureTab::PrintData(ValueWithError Te, ValueWithError Ne, bool correction)
{
    char temperature[256];
    char density[256];
    sprintf( temperature, "Te = %d eV +/- %d eV", int(Te.val), int(Te.error) );
    sprintf( density, "Ne = %.1f +/- %.2f ", Ne.val, Ne.error );
    
    //m_temperatureVal->SetText("");
    m_temperatureValNoCorrection->SetText("");
    m_densityValNoCorrection->SetText("");
    m_correction->SetText("");
    if( correction )
    {
        m_temperatureVal->SetText(temperature);
        m_densityVal->SetText(density);
    }
    else
    {
        m_correction->SetText("No correction");
        m_temperatureValNoCorrection->SetText(temperature);
        m_densityValNoCorrection->SetText(density);
    }
}

void MeasureTab::DrawData(std::vector<std::pair<double, double> > line, std::vector<std::pair<double, ValueWithError> > points, bool correction)
{
    m_canvas->cd();
    
    if( correction )
    {
        if( Draw( line, points, m_grChanelWidth, m_pointsChanelWidth ) )
        {
            m_canvas->SetEditable(true);
            m_pointsChanelWidth->Draw("AP");
            m_grChanelWidth->Draw("L");
            m_canvas->Update();
            m_canvas->SetEditable(false);
        }
        else
            SetWarningText( std::string("No valid signal data to draw. Check calibrations and signal histograms") );
    }
    else
    {
        if( Draw( line, points, m_gr, m_points ) )
        {
            m_canvas->SetEditable(true);
            m_points->Draw("P");
            m_gr->Draw("L");
            m_canvas->Update();
            m_canvas->SetEditable(false);
        }
        else
            SetWarningText( std::string("No valid signal data to draw. Check calibrations and signal histograms") );
    }
}

// Draw graphs. Failed to make TMultiGraph work properly in ROOT 5.13
// so use simple graph superposition
bool MeasureTab::Draw(std::vector<std::pair<double, double> > line, std::vector<std::pair<double, ValueWithError> > points,
                        TGraph *grLine, TGraphErrors *grPoints)
{
    while ( grLine->GetN() > 0 )
        grLine->RemovePoint(0);

    bool draw = false;
    if( line.size() > 1 )
    {
        if ( std::isnormal(line[0].second) && std::isnormal(line[1].second) )
        {
            grLine->SetPoint(0, line[0].first, line[0].second);
            grLine->SetPoint(1, line[1].first, line[1].second);

            draw = true;
        }
    }
    
    while ( grPoints->GetN() > 0 )
        grPoints->RemovePoint(0);

    for( int i = 0; i < points.size(); ++i )
    {
        if( std::isnormal(points[i].second.val)  )
        {
            grPoints->SetPoint(i, points[i].first, points[i].second.val);
            grPoints->SetPointError(i, 0, points[i].second.error);

            draw = true;
        }
    }

    return draw;
}

void MeasureTab::SetWarningText(std::string text)
{
    std::stringstream str;
    time_t tm = time(NULL);
    str << asctime(localtime(&tm)) << ": " << text;
    m_warning->AddLine(str.str ().c_str());
}
